预览接口【订阅号与服务号认证后均可用】
开发者可通过该接口发送消息给指定用户,在手机端查看消息的样式和排版。为了满足第三方平台开发者的需求,在保留对openID预览能力的同时,增加了对指定微信号发送预览的能力,但该能力每日调用次数有限制(100次),请勿滥用。
接口调用请求说明
http请求方式: POST https://api.weixin.qq.com/cgi-bin/message/mass/preview?access_token=ACCESS_TOKEN
POST数据说明
POST数据示例如下:
图文消息(其中media_id与根据分组群发中的media_id相同):
{
"touser":"OPENID",
"mpnews":{
"media_id":"123dsdajkasd231jhksad"
},
"msgtype":"mpnews"
}
文本:
{
"touser":"OPENID",
"text":{
"content":"CONTENT"
},
"msgtype":"text"
}
语音(其中media_id与根据分组群发中的media_id相同):
{
"touser":"OPENID",
"voice":{
"media_id":"123dsdajkasd231jhksad"
},
"msgtype":"voice"
}
图片(其中media_id与根据分组群发中的media_id相同):
{
"touser":"OPENID",
"image":{
"media_id":"123dsdajkasd231jhksad"
},
"msgtype":"image"
}
视频(其中media_id与根据分组群发中的media_id相同):
{
"touser":"OPENID",
"mpvideo":{ "media_id":"IhdaAQXuvJtGzwwc0abfXnzeezfO0NgPK6AQYShD8RQYMTtfzbLdBIQkQziv2XJc",
},
"msgtype":"mpvideo"
}
卡券:
{ "touser":"OPENID",
"wxcard":{
"card_id":"123dsdajkasd231jhksad",
"card_ext": "{"code":"","openid":"","timestamp":"1402057159","signature":"017bb17407c8e0058a66d72dcc61632b70f511ad"}"
},
"msgtype":"wxcard"
}
请注意,上述JSON数据中的touser字段都可以改为towxname,这样就可以针对微信号进行预览(而非openID),towxname和touser同时赋值时,以towxname优先。修改后JSON数据如下(以图文消息为例): 图文消息:
{
"towxname":"示例的微信号",
"mpnews":{
"media_id":"123dsdajkasd231jhksad"
},
"msgtype":"mpnews"
}
参数说明
touser
接收消息用户对应该公众号的openid,该字段也可以改为towxname,以实现对微信号的预览
msgtype
群发的消息类型,图文消息为mpnews,文本消息为text,语音为voice,音乐为music,图片为image,视频为video,卡券为wxcard
media_id
用于群发的消息的media_id
content
发送文本消息时文本的内容
返回说明
返回数据示例(正确时的JSON返回结果):
{
"errcode":0,
"errmsg":"preview success",
"msg_id":34182
}
参数说明
errcode
错误码
errmsg
错误信息
msg_id
消息ID
一、我们测试一下图文素材预览群发
【重要说明!!!】1、这里发现一个文档bug,预览群发图文素材时候touser至少需要两个openid以上
![](https://img-blog.csdnimg.cn/20200121151804435.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTM1MjEyMjA=,size_16,color_FFFFFF,t_70)
2、图文素材预览接口测试账号暂时没有权限
![](https://img-blog.csdnimg.cn/20200121152328912.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTM1MjEyMjA=,size_16,color_FFFFFF,t_70)
现在我们看代码演示发送图文消息预览
![](https://img-blog.csdnimg.cn/20200121152438637.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTM1MjEyMjA=,size_16,color_FFFFFF,t_70)
package com.xu.wemall.components.weixin;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xu.wemall.commons.constants.URIConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import java.util.List;
/**
* 预览接口【订阅号与服务号认证后均可用】
*/
@Slf4j
@Component
public class PreviewUtil {
@Autowired
private RestTemplate restTemplate;
@Autowired
private AccessTokenUtil accessTokenUtil;
private String createPreviewString(List openIdList, String mediaId, String content, String msgtype){
JSONObject data = new JSONObject();
JSONArray touser = new JSONArray();
touser.addAll(openIdList);
data.put("touser",touser);
JSONObject type = new JSONObject();
if(mediaId != null){
type.put("media_id",mediaId);
}
//图文消息
if(msgtype.equalsIgnoreCase("mpnews")){
data.put("mpnews",type);
}else if(msgtype.equalsIgnoreCase("text")){
data.put("text",type); //文本
type.put("content",content);
}else if(msgtype.equalsIgnoreCase("voice")){
data.put("voice",type); //声音
}else if(msgtype.equalsIgnoreCase("image")){
data.put("image",type); //图片
}else if(msgtype.equalsIgnoreCase("mpvideo")){
data.put("mpvideo",type); //声音
}else if(msgtype.equalsIgnoreCase("wxcard")) {
data.put("wxcard", type); //卡券
}
if(msgtype !=null){
data.put("msgtype",msgtype);
}
return data.toJSONString();
}
/**
*预览接口
*/
public String preview(List openIdList, String mediaId, String content, String msgtype) {
String accessToken = accessTokenUtil.getAccessToken();
if (accessToken != null) {
log.info("URL{}", URIConstant.PREVIEW_URL);
String url = URIConstant.PREVIEW_URL.replace("ACCESS_TOKEN", accessToken);
log.info("PREVIEW_URL:{}", url);
//将菜单对象转换成JSON字符串
String dataString = this.createPreviewString(openIdList, mediaId, content, msgtype);
log.info("dataString:{}",dataString);
//发起POST请求创建菜单
String jsonObject = restTemplate.postForObject(url, dataString,String.class);
return jsonObject;
}
return null;
}
}
在swagger中添加测试方法
![](https://img-blog.csdnimg.cn/20200121152539227.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTM1MjEyMjA=,size_16,color_FFFFFF,t_70)
package com.xu.wemall.controller.weixin;
import com.xu.wemall.components.weixin.PreviewUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* 类名称: previewController
* 类描述: 预览API
*/
@Slf4j
@RestController
@Api(tags = "预览接口")
@RequestMapping(value = "/preview")
public class PreviewController {
@Autowired
private PreviewUtil previewUtil;
/**
* 根据标签进行预览
*/
@ApiOperation(value = "预览群发接口")
@RequestMapping(value = "/preview", method = RequestMethod.POST)
@ApiImplicitParams({
//@ApiImplicitParam(name="openId",value="接收消息用户对应该公众号的openid,该字段也可以改为towxname,以实现对微信号的预览", paramType="query",dataType="String"),
@ApiImplicitParam(name="mediaId",value="用于群发的消息的media_id"),
@ApiImplicitParam(name="content",value="发送文本消息时文本的内容"),
@ApiImplicitParam(name="msgtype",value="群发的消息类型,图文消息为mpnews,文本消息为text,语音为voice,音乐为music,图片为image,视频为video,卡券为wxcard", paramType="query",dataType="Integer")
})
public Object preview(@RequestParam(value = "touser") List touser, String mediaId, String content, String msgtype) {
String tempString = previewUtil.preview(touser, mediaId,content, msgtype);
return tempString;
}
}
swagger测试文本消息预览,填写正确的参数
![](https://img-blog.csdnimg.cn/20200121152829291.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTM1MjEyMjA=,size_16,color_FFFFFF,t_70)
发送成功,返回了一个msg_id
![](https://img-blog.csdnimg.cn/20200121153115322.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTM1MjEyMjA=,size_16,color_FFFFFF,t_70)
![](https://img-blog.csdnimg.cn/20200121153212644.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTM1MjEyMjA=,size_16,color_FFFFFF,t_70)
重要说明:当我们短时间发送重复内容会发生什么呢?
![](https://img-blog.csdnimg.cn/20200121154528784.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTM1MjEyMjA=,size_16,color_FFFFFF,t_70)
我们看看官方开发文档怎么说的
使用 clientmsgid 参数,避免重复推送
一、群发接口新增 clientmsgid 参数,开发者调用群发接口时可以主动设置 clientmsgid 参数,避免重复推送。
群发时,微信后台将对 24 小时内的群发记录进行检查,如果该 clientmsgid 已经存在一条群发记录,则会拒绝本次群发请求,返回已存在的群发msgid,开发者可以调用“查询群发消息发送状态”接口查看该条群发的状态。
二、新增返回码
返回码结果
45065
相同 clientmsgid 已存在群发记录,返回数据中带有已存在的群发任务的 msgid
45066
相同 clientmsgid 重试速度过快,请间隔1分钟重试
45067
clientmsgid 长度超过限制
微信公众号还提供了设置和查询群发速度接口,更多细节请读者自行仔细阅读微信公众号开发文档更多详细内容,谢谢观看,我们下回再见!
===============================================================================
如果您觉得此文有帮助,可以小小打赏一下,持续更新更有动力哟!
![](https://img2020.cnblogs.com/blog/1501920/202004/1501920-20200402133129576-79870337.png) ![](https://img2020.cnblogs.com/blog/1501920/202004/1501920-20200402133221455-2112921293.png)
|